/*
 * (C) Copyright 2012, by Tim Xie.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.superapk.diamond.http;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import com.superapk.diamond.util.HttpImageCacheUtil;
import com.superapk.diamond.util.LogUtil;
import android.os.Handler;

/**
 * Http请求管理类，负责向服务器发送请求，同时接收服务端返回的数据
 * 
 * @author     Tim Xie [tim.xie2008@gmail.com]
 * @date       2013-2-21
 * 
 */

public class HttpHandler {
	
	public final static int HTTP_IO_EXCEPTION = 9001;
	
	private Handler mHandler = new Handler();
	
	/**
	 * 向服务器发送请求，会异步执行该操作
	 * 
	 * @param path 请求url
	 * @param param 请求参数
	 * @param callback 回调接口，请求成功或失败时调用
	 * @throws Exception 当请求url或请求参数为空时抛出异常
	 */
	public void post(String path,String param, HttpHandlerCallback callback) throws IllegalArgumentException {
		if(path == null || param == null){
			throw new IllegalArgumentException("path or params is null!");
		}
		startTask(path, callback, param);
	}
	
	/**
	 * 从网络获取资源
	 * @param path
	 * @param callback
	 * @throws Exception
	 */
	public void get(String path, HttpHandlerCallback callback) throws IllegalArgumentException{
		if(path==null){
			throw new IllegalArgumentException("path is null!");
		}
		startTask(path, callback, null);
	}
	
	/**
	 * 从网络获取一张图片
	 * @param path
	 * @param callback
	 * @param useCache
	 */
	public void getHttpImage(String path, HttpHandlerCallback callback,boolean useCache){
		if(path==null){
			throw new IllegalArgumentException("path is null!");
		}
		startTask(path, callback, null,true);
	}
	
	/**
	 * 启动异步请求 
	 * @param path 请求url
	 * @param callback 回调接口，请求成功或失败时调用
	 * @param param 请求参数
	 */
	private void startTask(String path, HttpHandlerCallback callback,String param){
		this.startTask(path, callback, param,false);
	}
	
	/**
	 * 启动异步请求 
	 * @param path 请求url
	 * @param callback 回调接口，请求成功或失败时调用
	 * @param param 请求参数
	 * @param useCache 是否使用缓存
	 */
	private void startTask(String path, HttpHandlerCallback callback,String param,boolean useCache){
		HttpHandlerRunnable task = new HttpHandlerRunnable(useCache,path,param,callback);
		new Thread(task).start();
	} 
	
	class HttpHandlerRunnable implements Runnable{

		/**
		 * 标记是否在网络请求前检查本地的图片资源
		 */
		private boolean mUseImageCache = false;
		/**
		 * 请求url
		 */
		private String mPath;
		/**
		 * 标注是否是请求一张图片,默认是false
		 */
		private boolean isImage = false;
		/**
		 * 需要上传的参数
		 */
		private String mParam;
		/**
		 * 返回的数据
		 */
		private byte[] bytes;
		/**
		 * 请求回调接口
		 */
		private HttpHandlerCallback mCallback;
		
		HttpHandlerRunnable(boolean useImageCache,boolean isImage,String urlPath,String param,HttpHandlerCallback callback){
			this.mUseImageCache = useImageCache;
			this.isImage = isImage;
			this.mPath = urlPath;
			this.mParam = param;
			this.mCallback = callback;
		}
		
		HttpHandlerRunnable(boolean useImageCache,String urlPath,String param,HttpHandlerCallback callback){
			this(useImageCache,false,urlPath,param,callback);
		}
		
		@Override
		public void run() {
			if(mUseImageCache){
				//首先检查本地是否存在图片缓存
				bytes = HttpImageCacheUtil.getCacheBitmapData(mPath);
				if(bytes != null){
					if(mCallback != null){
						mHandler.post(new Runnable(){
							@Override
							public void run() {
								mCallback.serverResponse(bytes);
							}
						});
					}
					return;
				}
			}
			HttpURLConnection conn = null;
			PrintWriter out = null;
			InputStream inStream = null;
			ByteArrayOutputStream outputStream = null;
			try {
				URL url = new URL(mPath);
				conn = (HttpURLConnection)url.openConnection();
				if(mParam == null){
					conn.setRequestMethod("GET");
					conn.setConnectTimeout(5000);
					conn.setRequestProperty("Accept", "*/*");
				}else{
					conn.setRequestMethod("POST");
					conn.setConnectTimeout(5000);
					conn.setDoOutput(true);
					conn.setDoInput(true);
					conn.setRequestProperty("Accept", "*/*");
				}
				if(isImage || mPath.toLowerCase().endsWith(".jpg") || mPath.toLowerCase().endsWith(".png") 
						|| mPath.toLowerCase().endsWith(".gif") || mPath.toLowerCase().endsWith(".jpeg")){
					conn.setRequestProperty("Content-Type", "image/*");
				}
				else{
					conn.setRequestProperty("Content-Type", "text/html");
				}
				conn.setRequestProperty("Connection", "Keep-Alive");
				if(mParam != null){
					out = new PrintWriter(conn.getOutputStream());
					out.print(mParam);
					out.flush();
				}
				final int responseCode = conn.getResponseCode();
				//成功
				if(responseCode == HttpURLConnection.HTTP_OK){
					outputStream = new ByteArrayOutputStream();
					inStream = conn.getInputStream();
					byte[] buffer = new byte[1024];
					int len = 0;
					while ((len = inStream.read(buffer)) != -1) {
						outputStream.write(buffer, 0, len);
					}
					bytes = outputStream.toByteArray();
				}else{//失败
					LogUtil.e(mPath + ":" + responseCode);
					//调用者根据此Code判断是否连接成功
					if(mCallback != null){
						mHandler.post(new Runnable(){
							@Override
							public void run() {
								mCallback.serverResponseError(responseCode);
							}
						});
					}
				}
			} catch (Exception e) {
				LogUtil.e(mPath + ":" + e.toString());
				if(mCallback != null){
					mHandler.post(new Runnable(){
						@Override
						public void run() {
							mCallback.serverResponseError(HTTP_IO_EXCEPTION);
						}
					});
				}
			} finally {
				if(out!=null){
					out.close();
				}
				if(outputStream != null){
					try {
						outputStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if(inStream!=null){
					try {
						inStream.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if(conn!=null){
					conn.disconnect();
				}
			}
			if(mUseImageCache){
				//如果需要用缓存，把该图片放入到SDCard
				HttpImageCacheUtil.addCache(mPath, bytes);
			}
			if(bytes != null){
				mHandler.post(new Runnable(){
					@Override
					public void run() {
						mCallback.serverResponse(bytes);
					}
				});
			}
		}
		
	}
}
